package io.xxx.aurora.client.netty

import io.netty.bootstrap.Bootstrap
import io.netty.channel.Channel
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.ChannelInitializer
import io.netty.channel.SimpleChannelInboundHandler
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.nio.NioSocketChannel
import io.netty.handler.codec.string.StringDecoder
import io.netty.handler.codec.string.StringEncoder
import java.util.concurrent.TimeUnit

fun main() {
    val client = EchoClient("localhost", 9100)
    client.start()
    val channel = client.channel
    for (i in 1..5) {
        channel.writeAndFlush("123")
        TimeUnit.SECONDS.sleep(1)
    }
    println("send completed.")
    channel.close()
}

class EchoClient(
    private val host: String,
    private val port: Int,
) {

    lateinit var channel: Channel

    fun start() {
        val group = NioEventLoopGroup()
        val b = Bootstrap()
        b.group(group)
            .channel(NioSocketChannel::class.java)
            .handler(object : ChannelInitializer<SocketChannel>() {
                override fun initChannel(ch: SocketChannel) {
                    ch.pipeline()
                        .addLast(StringEncoder())
                        .addLast(StringDecoder())
                        .addLast(EchoInboundHandler())
                }
            })
        val f = b.connect(host, port).sync()
        f.addListener {
            if (it.isSuccess) {
                println("连接服务器成功")
            } else {
                println("连接服务器失败")
                f.cause().printStackTrace()
                group.shutdownGracefully() //关闭线程组
            }
        }
        channel = f.channel()
    }
}

class EchoInboundHandler : SimpleChannelInboundHandler<String>() {

    override fun channelActive(ctx: ChannelHandlerContext) {
//        ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8))
        super.channelActive(ctx)
    }

    override fun channelRead0(ctx: ChannelHandlerContext, msg: String) {
        println("Client received: $msg")
    }

    override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
        cause.printStackTrace()
        ctx.close()
    }
}